package cn.itcast.model.multithread.pool;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import cn.itcast.model.multithread.pool.exception.ConcurrencyFailureException;
import cn.itcast.model.multithread.pool.facade.ExectueCallBack;
import cn.itcast.model.multithread.pool.utils.ExceptionUtils;

/**
 * 线程管理工具类
 */
public class ThreadManager {
	private static ExecutorService createCustomExecutorService(int poolSize, final String method) {
		// 设置核心线程数
		int coreSize = Runtime.getRuntime().availableProcessors();// 返回系统CUP数量
        if (poolSize < coreSize) {
			coreSize = poolSize;
		}

        // 线程创建工厂
        ThreadFactory tf = new ThreadFactory() {
        	@Override
            public Thread newThread(Runnable r) {
                Thread t = new Thread(r, "thread created at ThreadManager method [" + method + "]");
                t.setDaemon(true);
                return t;
            }
        };

        // 无界阻塞队列 -- 可根据需求更换
        BlockingQueue<Runnable> queueToUse = new LinkedBlockingQueue<Runnable>();

		/**
		 * 丢弃策略
		 * 1、AbortPolicy策略
		 * 		该策略直接抛出异常
		 * 2、CallerRunsPolicy策略
		 * 		只要线程池未关闭，该策略直接在调用者线程（如Main方法）中运行当前被丢弃的任务
		 * 		显然这样不会真的丢弃任务，但是，调用者线程性能可能急剧下降
		 * 3、DiscardPolicy策略
		 *		默默的丢弃无法处理的任务，不予任何处理
		 * 4、DiscardOldestPolicy策略
		 * 		丢弃最老的一个请求任务，也就是丢弃一个即将被执行的任务，并尝试再次提交当前任务
		 */
        final ThreadPoolExecutor executor = new ThreadPoolExecutor(coreSize, poolSize, 60,
        		TimeUnit.SECONDS, queueToUse, tf, new ThreadPoolExecutor.CallerRunsPolicy());// 创建线程池
		executor.allowCoreThreadTimeOut(true) ;// 让所有线程都支持超时，这意味着如果项目很闲，就会将项目组的成员都撤走。
        return executor;
	}

	/**
	 * list 集合分页显示截断 用于切割任务
	 * @param list 待分页截断集合
	 * @param skip 起始记录号
	 * @param pageSize 每页大小
	 * @param <T>
	 * @return
	 */
	public static <T> List<T> getSubListPage(List<T> list, int skip,int pageSize) {
	    if (list == null || list.isEmpty()) {
			return null;
		}

	    int startIndex = skip;
	    int endIndex = skip + pageSize;
	    if (startIndex > endIndex || startIndex > list.size()) {
	      return null;
	    }
	    
	    if (endIndex > list.size()) {
	      endIndex = list.size();
	    }
	    
	    return list.subList(startIndex, endIndex);
	}

	/**
	 * 执行器批量执行任务
	 * @param paramCollection
	 * @param ecb
	 */
	public static void doFunction(Collection<?> paramCollection,final ExectueCallBack ecb){
	    //构建执行器
	    ExecutorService executor = createCustomExecutorService(Runtime.getRuntime().availableProcessors(), "batchExecuteProjection");
	    try {
	      //监视器
	      final CountDownLatch latch = new CountDownLatch(paramCollection.size());
	      final StringBuffer exceptionStaktrace = new StringBuffer();
	      Iterator<?> iter = paramCollection.iterator();
	      while (iter.hasNext()) {
	        final Object entity = iter.next();
	        Runnable task = new Runnable() {
	          public void run() {
	            try {
	              ecb.doExectue(entity);
	            } catch (Throwable t) {
	              exceptionStaktrace.append(ExceptionUtils.getFullStackTrace(t));
	            } finally {
	              latch.countDown();
	            }
	          }
	        };
	        executor.execute(task);//并行调度
	      }

	      try {
	        latch.await();//监视器等待所有线程执行完毕
	      } catch (InterruptedException e) {
	        //调度异常
	        throw new ConcurrencyFailureException(
	            "unexpected interruption when re-arranging parameter collection into sub-collections ",e);
	      }

	      if (exceptionStaktrace.length() > 0) {
	        //业务异常
	        throw new ConcurrencyFailureException(
	            "unpected exception when re-arranging parameter collection, check previous log for details.\n"+ exceptionStaktrace);
	      }
	    } finally {
	      executor.shutdown();//执行器关闭
		}
	}
}
